package com.xnf.ssmweb.aop;

import com.xnf.ssmweb.domain.SysLog;
import com.xnf.ssmweb.service.SysLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * Created by chendx on 2021/4/8.
 */
@Component
@Controller
@RequestMapping("sysLog")
@Aspect
public class LogAop {
    private Date visitTime; //访问时间
    private Class clazz; //访问的类
    private Method method; //访问的方法

    @Autowired
    private SysLogService sysLogService;

    @Autowired
    private HttpServletRequest request;


    @Before("execution(* com.xnf.ssmweb.controller.*.*(..))")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException {
        visitTime = new Date(); //设置当前时间
        clazz = jp.getTarget().getClass(); //获取目标类
        String methodName = jp.getSignature().getName(); //获取目标方法名称
        Object[] args = jp.getArgs(); //获取目标方法参数
        if (args != null && args.length !=0){
            //将目标方法参数类型存入Class[]
            Class[] classes = new Class[args.length];
            for (int i = 0;i < classes.length;i++){
                classes[i] = args[i].getClass();
            }
            method = clazz.getMethod(methodName, classes);//有参方法
        }else{
            method = clazz.getMethod(methodName);//无参方法
        }
    }

    @After("execution(* com.xnf.ssmweb.controller.*.*(..))")
    public void doAfter(JoinPoint jp){
        Long time = new Date().getTime() - visitTime.getTime();
        //获取操作者信息
        SecurityContext securityContext = new SecurityContextHolder().getContext();
        UserDetails userInfo = (UserDetails) securityContext.getAuthentication().getPrincipal();
        String username = userInfo.getUsername();
        //获取访问的IP
        String ip = request.getRemoteAddr();
        if (clazz != null && method != null && clazz != LogAop.class){
            RequestMapping classMapping = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
            if (classMapping != null){
                String[] clazzValues = classMapping.value();
                RequestMapping methodMapping =  method.getAnnotation(RequestMapping.class);
                String[] methodValues = methodMapping.value();
                String clazzValue = clazzValues[0];
                String methodValue = methodValues[0];

                SysLog sysLog = new SysLog();
                sysLog.setIp(ip);
                sysLog.setMethod("[类名]"+clazz.getName()+"[方法名]"+method.getName());
                sysLog.setVisitTime(visitTime);
                sysLog.setUrl(clazzValue+methodValue);
                sysLog.setUsername(username);
                sysLog.setExecutionTime(String.valueOf(time));

                sysLogService.saveSysLog(sysLog);
            }
        }
    }

    @RequestMapping("/toSysLog")
    public ModelAndView toSysLog(){
        ModelAndView mav = new ModelAndView();
        mav.addObject("sysLogs",sysLogService.findSysLogs());
        mav.setViewName("syslog-list");
        return mav;
    }
}
